package test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.hibernate.HibernateException;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import trip.*;
import dao.*;

public class Time_tableDAOTest extends Assert {
	
	private Time_tableDAO ttD = Factory.getInstance().getTime_tableDAO();
	private CompanyDAO cD = Factory.getInstance().getCompanyDAO();
	private RouteDAO rD = Factory.getInstance().getRouteDAO();
	private TripDAO tD = Factory.getInstance().getTripDAO();
	
	@DataProvider
	public Object[][] timeTableData() {
		return new Object[][] {
				{1, 1, "2015-01-12 18:00:00", "2015-01-12 18:00:00", 1, true},
				
				{null, 1, "2015-01-12 18:00:00", "2015-01-12 18:00:00", 1, false},
				{1, null, "2015-01-12 18:00:00", "2015-01-12 18:00:00", 1, false},
				{1, 1, null, "2015-01-12 18:00:00", 1, false},
				{1, 1, "2015-01-12 18:00:00", null, 1, false},
				{1, 1, "2015-01-12 18:00:00", "2015-01-12 18:00:00", null, true},
				
				{null, null, "2015-01-12 18:00:00", "2015-01-12 18:00:00", 1, false},
				{null, 1, null, "2015-01-12 18:00:00", 1, false},
				{null, 1, "2015-01-12 18:00:00", null, 1, false},
				{null, 1, "2015-01-12 18:00:00", "2015-01-12 18:00:00", null, false},
				{1, null, null, "2015-01-12 18:00:00", 1, false},
				{1, null, "2015-01-12 18:00:00", null, 1, false},
				{1, null, "2015-01-12 18:00:00", "2015-01-12 18:00:00", null, false},
				{1, 1, null, null, 1, false},
				{1, 1, null, "2015-01-12 18:00:00", null, false},
				{1, 1, "2015-01-12 18:00:00", null, null, false},
				
				{null, null, null, "2015-01-12 18:00:00", 1, false},
				{null, null, "2015-01-12 18:00:00", null, 1, false},
				{null, null, "2015-01-12 18:00:00", "2015-01-12 18:00:00", null, false},
				{null, 1, null, null, 1, false},
				{null, 1, null, "2015-01-12 18:00:00", null, false},
				{null, 1, "2015-01-12 18:00:00", null, null, false},
				{1, null, null, null, 1, false},
				{1, null, null, "2015-01-12 18:00:00", null, false},
				{1, null, "2015-01-12 18:00:00", null, null, false},
				{1, 1, null, null, null, false},
				
				{1, null, null, null, null, false},
				{null, 1, null, null, null, false},
				{null, null, "2015-01-12 18:00:00", null, null, false},
				{null, null, null, "2015-01-12 18:00:00", null, false},
				{null, null, null, null, 1, false},
				
				{null, null, null, null, null, false}
		};
	}
	
	@Test(dataProvider = "timeTableData")
	public void dataTest(Integer stop_number, Integer price, String arrival, 
						 String departure, Integer vacant_seats, boolean expected) {
		Company company = null;
		Route route = null;
		Trip trip = null;
		try {
			Integer count = ttD.getAll().size();
			assertNotNull(count);
			company = new Company(1, "x");
			route = new Route(1, 10, "x", true);
			trip = new Trip(1, 1, route, company, 10);
			SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date arrivalT = (arrival == null) ? null : parser.parse(arrival),
				 departureT = (departure == null) ? null : parser.parse(departure);
			Time_table tt = new Time_table(1, trip, stop_number, price, arrivalT, departureT, vacant_seats);
			rD.create(route);
			cD.create(company);
			tD.create(trip);
			ttD.create(tt);
			Time_table tmpTt = ttD.getById(tt.getId());
			assertNotNull(tmpTt);
			assertEquals(tmpTt.getId(), tt.getId());
			assertTrue(tmpTt.getTrip().equals(tt.getTrip()));
			assertEquals(tmpTt.getStop_number(), tt.getStop_number());
			assertEquals(tmpTt.getPrice(), tt.getPrice());
			assertEquals(tmpTt.getDeparture(), tt.getDeparture());
			assertEquals(tmpTt.getArrival(), tt.getArrival());
			assertEquals(tmpTt.getVacantSeats(), tmpTt.getTrip().getSeats());
			tt = tmpTt; 
			tt.setStop_number(tt.getStop_number() + 1);
			ttD.update(tt);
			tmpTt = ttD.getById(tt.getId());
			assertNotNull(tmpTt);
			assertEquals(tmpTt.getId(), tt.getId());
			assertTrue(tmpTt.getTrip().equals(tt.getTrip()));
			assertEquals(tmpTt.getStop_number(), tt.getStop_number());
			assertEquals(tmpTt.getPrice(), tt.getPrice());
			assertEquals(tmpTt.getDeparture(), tt.getDeparture());
			assertEquals(tmpTt.getArrival(), tt.getArrival());
			assertEquals(tmpTt.getVacantSeats(), tmpTt.getTrip().getSeats());
			rD.delete(route);
			cD.delete(company);
			tmpTt = ttD.getById(tt.getId());
			assertNull(tmpTt);
			assertEquals(ttD.getAll().size(), count.intValue());
		} catch(ParseException ex) {
			fail();
		} catch(HibernateException ex) {
			assertFalse(expected);
			if (route != null)
				rD.delete(route);
			if (company != null)
				cD.delete(company);
		}
	}
	
	@Test
	public void getByTripTest() {
		List<Time_table> tts = ttD.getAll();
		assertNotNull(tts);
		List<Trip> trips = tD.getAll();
		assertNotNull(trips);
		for(Trip trip : trips) {
			List<Time_table> ttByT = ttD.getByTrip(trip);
			assertNotNull(ttByT);
			if (ttByT.size() != 0) {
				for(Time_table tt : ttByT) {
					assertTrue(tt.getTrip().equals(trip));
				}
			}
			else {
				for(Time_table tt : tts) {
					assertFalse(tt.getTrip().equals(trip));
				}
			}
		}
	}
	
	@Test
	public void getByRouteTest() {
		List<Time_table> tts = ttD.getAll();
		assertNotNull(tts);
		List<Route> routes = rD.getAll();
		assertNotNull(routes);
		for(Route route : routes) {
			List<Time_table> ttByR = ttD.getByRoute(route);
			assertNotNull(ttByR);
			if (ttByR.size() != 0) {
				for(Time_table tt : ttByR) {
					assertTrue(tt.getTrip().getRoute().equals(route));
				}
			} 
			else {
				for(Time_table tt : tts) {
					assertFalse(tt.getTrip().getRoute().equals(route)); 
				}
			}
		}
	}
}